export type FileProgressCallback = (loaded: number, total: number) => void;

export default function send(
    url: string,
    method: string = "GET",
    options: Record<string, any>,
    onProgress: FileProgressCallback | null | undefined,
    onComplete: ((err: Error | null, data?: any) => void),
): XMLHttpRequest {
    const xhr = new XMLHttpRequest();
    const errInfo = `download failed: ${url}, status: `;

    xhr.open(method, url, true);

    if (options.xhrResponseType !== undefined) {
        xhr.responseType = options.xhrResponseType as XMLHttpRequestResponseType;
    }

    if (options.xhrWithCredentials !== undefined) {
        xhr.withCredentials = options.xhrWithCredentials as boolean;
    }

    if (options.xhrMimeType !== undefined && xhr.overrideMimeType) {
        xhr.overrideMimeType(options.xhrMimeType as string);
    }

    if (options.xhrTimeout !== undefined) {
        xhr.timeout = options.xhrTimeout as number;
    }

    if (options.xhrHeader) {
        for (const header in options.xhrHeader) {
            xhr.setRequestHeader(header, options.xhrHeader[header] as string);
        }
    }

    xhr.onload = (): void => {
        if (xhr.status === 200 || xhr.status === 0) {
            if (onComplete) {
                onComplete(null, xhr.response);
            }
        } else if (onComplete) {
            onComplete(new Error(`${errInfo}${xhr.status}(no response)`));
        }
    };

    if (onProgress) {
        xhr.onprogress = (e): void => {
            if (e.lengthComputable) {
                onProgress(e.loaded, e.total);
            }
        };
    }

    xhr.onerror = (): void => {
        if (onComplete) { onComplete(new Error(`${errInfo}${xhr.status}(error)`)); }
    };

    xhr.ontimeout = (): void => {
        if (onComplete) { onComplete(new Error(`${errInfo}${xhr.status}(time out)`)); }
    };

    xhr.onabort = (): void => {
        if (onComplete) { onComplete(new Error(`${errInfo}${xhr.status}(abort)`)); }
    };

    xhr.send(null);

    return xhr;
}